/**
 * UIKit+GTSearchableTableViewController.m
 *
 * The contents of this file are subject to the Mozilla Public License Version 1.1 (the "License");
 * you may not use this file except in compliance with the License. You may obtain a copy of the License 
 * at http://www.mozilla.org/MPL/
 * Software distributed under the License is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND,
 * either express or implied. See the License for the specific language governing rights and limitations 
 * under the License.
 *
 * The Original Code is gcast-toolbox4iphone.
 *
 * The Initial Developers of the Original Code is Giannandrea Castaldi.
 */
#import "GTSearchableTableViewController.h"
#import "UIKit+GTExtensions.h"
#import "GTActivityNotifier.h"

@interface GTSearchableTableViewController ()
@property (nonatomic,retain) UITableView *tableView;
@property (nonatomic,retain) NSArray *allItems;
@property (nonatomic,retain) NSMutableArray *filteredItems;
@property (nonatomic,retain,readonly) UILocalizedIndexedCollation *collation;
@property (nonatomic,retain) NSArray *sections;
@property (nonatomic,retain) NSString *errorMessage;
@property (nonatomic,retain) UISearchDisplayController *searchController;

- (UITableViewCell*)tableView:(UITableView *)aTableView errorMessageCell:(NSString*)anErrorMessage;
- (CGFloat)tableView:(UITableView *)aTableView errorMessageCellHeight:(NSString*)anErrorMessage;
- (void)retrieveItemsOnMainThread;
- (void)didSelectItem:(id)item;
@end

@implementation GTSearchableTableViewController
@synthesize	tableView, allItems, filteredItems, errorMessage, searchController, sections;

- (id)initWithCollationStringSelector:(SEL)aCollationStringSelector {
  if ((self = [super init])) {
    self.allItems = [NSArray array];
    self.filteredItems = [NSMutableArray arrayWithArray:self.allItems];
    collationStringSelector = aCollationStringSelector;
  }
  return self;
}

- (void)loadView {
  self.view = [UIView viewUnderNavigationBar:self];
  UISearchBar *searchBar = [[[UISearchBar alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 44.0)] autorelease];
  self.tableView = [[[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain] autorelease];
  self.tableView.allowsSelection = TRUE;
  self.tableView.dataSource = self;
  self.tableView.delegate = self;
  self.tableView.scrollEnabled = TRUE;
  self.tableView.tableHeaderView = searchBar;
  [self.view addSubview:self.tableView];
  [self.tableView putAtTheTopAndFillSuperview];
  
  self.searchController = [[[UISearchDisplayController alloc] initWithSearchBar:searchBar contentsController:self] autorelease];
  searchController.delegate = self;
  searchController.searchResultsDataSource = self;
  searchController.searchResultsDelegate = self;  
}

- (void)viewDidLoad {
  [self retrieveItems];
}

- (void)viewDidAppear:(BOOL)animated {
  [self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:TRUE];
  [super viewDidAppear:animated];
}

- (void)dealloc {
  [tableView release];
  [allItems  release];
  [filteredItems release];
	[collation release];
	[sections release];
  [errorMessage release];
  [searchController release];
  [super dealloc];
}

- (UILocalizedIndexedCollation*)collation {
  if (!collation) {
    collation = [[UILocalizedIndexedCollation currentCollation] retain];
  }
  return collation;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
  NSInteger result = 0;
  if (self.errorMessage || (self.filteredItems.count < self.allItems.count)) {
    result = 1;
  }
  else if (collation) {
    result = [[self.collation sectionTitles] count];
  }
  return result;
}

- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
  NSInteger result;
  if (self.errorMessage) {
    result = 1;
  }
  else if (self.filteredItems.count < self.allItems.count) {
    result = self.filteredItems.count;
  }
  else {
    result = [[self.sections objectAtIndex:section] count];
  }
  return result;
}

- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
  static NSString *cellIdentifier = @"Cell";
  UITableViewCell *cell;
  if (self.errorMessage) {
    cell = [self tableView:self.tableView errorMessageCell:self.errorMessage];
  }
  else if (self.filteredItems.count < self.allItems.count) {
    cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
      cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
    }
    id item = [self.filteredItems objectAtIndex:indexPath.row];
    cell.textLabel.text = [item performSelector:collationStringSelector];
  }
  else {
    cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
      cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
    }
    NSArray *itemsInSection = [self.sections objectAtIndex:indexPath.section];
    id item = [itemsInSection objectAtIndex:indexPath.row];
    cell.textLabel.text = [item performSelector:collationStringSelector];
  }
  return cell;
}

- (CGFloat)tableView:(UITableView *)aTableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
  CGFloat result;
  if (self.errorMessage) {
    result = [self tableView:self.tableView errorMessageCellHeight:self.errorMessage];
  }
  else {
    result = 44.0;
  }
  return result;
}

- (UITableViewCell*)tableView:(UITableView *)aTableView errorMessageCell:(NSString*)anErrorMessage {
  return nil;
}

- (CGFloat)tableView:(UITableView *)aTableView errorMessageCellHeight:(NSString*)anErrorMessage {  
  return 0;
}

- (NSString *)tableView:(UITableView *)aTableView titleForHeaderInSection:(NSInteger)section {
  return self.errorMessage || (self.filteredItems.count < self.allItems.count) ? nil : [[self.collation sectionTitles] objectAtIndex:section];
}

- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)aTableView {
  return self.errorMessage || (self.filteredItems.count < self.allItems.count) ? nil : [self.collation sectionIndexTitles];
}

- (NSInteger)tableView:(UITableView *)aTableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
  return self.errorMessage ? 0 : [self.collation sectionForSectionIndexTitleAtIndex:index];
}

- (void)tableView:(UITableView*)aTableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath {
  if (!self.errorMessage) {
    id item;
    if (self.filteredItems.count < self.allItems.count) {
      item = [self.filteredItems objectAtIndex:indexPath.row];
    }
    else {
      NSArray *itemsInSection = [self.sections objectAtIndex:indexPath.section];
      item = [itemsInSection objectAtIndex:indexPath.row];
    }
    [self didSelectItem:item];
  }
}

- (void)didSelectItem:(id)item {
  // To override
}

#pragma mark -
#pragma mark UISearchDisplayController Delegate Methods

- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString {
	[self.filteredItems removeAllObjects];
	for (id item in self.allItems)	{
		if ([[[item performSelector:collationStringSelector] lowercaseString] rangeOfString:[searchString lowercaseString]].location != NSNotFound) {
      [self.filteredItems addObject:item];
		}
	}
  self.sections = [self splitAndOrderArray:self.filteredItems usingCollation:self.collation stringSelector:collationStringSelector];
  return YES;
}

- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller {
  [self.filteredItems removeAllObjects];
  [self.filteredItems addObjectsFromArray:self.allItems];
  self.sections = [self splitAndOrderArray:self.filteredItems usingCollation:self.collation stringSelector:@selector(airlineName)];
}

#pragma mark -
#pragma mark utility methods
// This method must be overriden by subclasses to retrive items to show.
// After the items has been retrived subclasses must recall this methods: [super retriveItems].
- (void)retrieveItems {
  [self performSelectorOnMainThread:@selector(retrieveItemsOnMainThread) withObject:nil waitUntilDone:NO];
}

- (void)retrieveItemsOnMainThread {
  [GTActivityNotifier notifyEndActivity];
  [self.filteredItems removeAllObjects];
  [self.filteredItems addObjectsFromArray:self.allItems];
  self.sections = [self splitAndOrderArray:self.filteredItems usingCollation:self.collation stringSelector:@selector(airlineName)];
  [self.tableView reloadData];  
}

- (void)didReceiveMemoryWarning {
  NSLog(@"%@: didReceiveMemoryWarning", self);
}

@end